package com.fingard.remoting.client;

import java.util.ArrayList;
import java.util.Date;
import java.util.TimerTask;

import com.fingard.FGBiz;
import com.fingard.constant.Format;
import com.fingard.diagnostics.LogHelper;
import com.fingard.dsp.DSPCenter;
import com.fingard.dsp.bank.reqrespobj.ReqRespHeader;
import com.fingard.dsp.tcpserver.RequestNIO;
import com.fingard.dsp.tcpserver.SocketReceiver;
import com.fingard.remoting.TenantSocket;
import com.fingard.util.DateHelper;
import com.fingard.xml.XmlTextReader;

/**客户端，记录状态，socket对象*/
public class TenantClient extends TimerTask{

	private ArrayList<String> serverList;
	
	private String nowServerAddr;
	private int nowServerIdx;//当前连接采用的服务列表索引
	private Date lastConnTime;//上次连接时间
	private Date lastAccTime;//上次访问时间
	
	/**作为客户端的设置*/
	private TenantClientSet clientSet;
	private TenantSocket tenantSocket;
	public TenantClient(TenantClientSet pSet){
		clientSet = pSet;
		serverList = new ArrayList<String>();
		String[] slist = clientSet.remoteServerList.split(",");
		for(int i=0;i<slist.length;i++){
			serverList.add(slist[i]);
		}
		nowServerIdx = 0;
	}
	
	/**连接远程服务器
	 * @throws Exception */
	private boolean connectRemoteServer(int pIdx) throws Exception{
		synchronized(this){
			lastConnTime = new Date();
			if(serverList.size()>pIdx){
				nowServerAddr = serverList.get(pIdx);
				String[] ipprot = nowServerAddr.split(":");
				TenantSocket socket = new TenantSocket(ipprot[0], Integer.parseInt(ipprot[1]), clientSet.charset, clientSet.tenantCode);
				boolean retValue = socket.connect();
				tenantSocket = socket;
				return retValue;
			}else{
				throw new Exception("取远程服务器地址时，索引越界");
			}
		}
	}
	
	public boolean isConnected(){
		if(tenantSocket != null){
			return tenantSocket.isConnected;
		}else{
			return false;
		}
	}
	
	public boolean connToAnyServer(){
		boolean connResult = false;
		try {
			for(int i=0;i<serverList.size();i++){
				connResult = connectRemoteServer(nowServerIdx);
				if(!connResult){
					nowServerIdx++;
					if(nowServerIdx>=serverList.size()){
						nowServerIdx = 0;
					}
				}else{
					break;
				}
			}
		} catch (Exception e) {
			FGBiz.limitMsg.exception("TenantClient.connectRemoteServer", e);
		}
		return connResult;
	}
	
	@Override
	public void run() {
		if(lastConnTime!=null){
			double diffSecs = DateHelper.getDifferSecs(new Date(), lastConnTime);
			if(diffSecs<clientSet.hbIntervalSecs){
				return;
			}
		}
		if(tenantSocket.lastRecDate != null){
			double diffSecs = DateHelper.getDifferSecs(new Date(), tenantSocket.lastRecDate);
			if(diffSecs>15){
				tenantSocket.isConnected = false;
			}
		}
		//保持连接
		if(tenantSocket != null && !tenantSocket.isConnected){
			tenantSocket.disconnect();
			connToAnyServer();
		}
	}

	public void dealReq() throws Exception{
		if(tenantSocket == null || !tenantSocket.isConnected){
			connToAnyServer();
		}
		if(tenantSocket!= null && tenantSocket.isConnected){
			ReqRespHeader bankHeader = new ReqRespHeader();
			try{
				SocketReceiver reqSocketReceiver = tenantSocket.receiveBytes(bankHeader);
				if(reqSocketReceiver.isCompleted && reqSocketReceiver.readedLength > 0 && reqSocketReceiver.contentStartIndex >= 0){
					String tmpStrReq = new String(reqSocketReceiver.reqBytes, reqSocketReceiver.contentStartIndex, reqSocketReceiver.contentLength, reqSocketReceiver.charsetName);
					//11属心跳包
					if(tmpStrReq.length() != 11){
						XmlTextReader xmlReader = new XmlTextReader(tmpStrReq);
			            bankHeader = DSPCenter.getReqRespHeader(xmlReader);
			            RequestNIO reqNIO = new RequestNIO(reqSocketReceiver);
			            reqNIO.isRemotingInvoke = true;
			            reqNIO.connTime = new Date();
			            reqNIO.recCompleteTime = new Date();
			            reqNIO.GetReqRespHeader();
			            FGBiz.bankServer.addRequest(reqNIO);
					}
					
				}else if(reqSocketReceiver.hasError){
					tenantSocket.isConnected = false;
					FGBiz.limitMsg.error("TenantClient.dealReq", reqSocketReceiver.errMsg);
				}
				lastAccTime = new Date();
			}catch(Throwable e){
				String tMsg = LogHelper.getStackTrace(e);
				if(!tMsg.contains("timed out") && !tMsg.contains("超时")){
					tenantSocket.isConnected = false;
					throw new Exception(tMsg);
				}
			}
		}else{
			String msg = "未连接远程服务器，地址："+nowServerAddr;
			if(lastAccTime != null){
				msg+="，上次正常访问时间："+Format.DateTimeSSSFormat.format(lastAccTime);
			}
			throw new Exception(msg);
		}
	}
}
